package se.penselnsvag.bookdb.tech.log {
	
import flash.utils.getQualifiedClassName;

import se.penselnsvag.bookdb.tech.collection.HashMap;
import se.penselnsvag.bookdb.tech.collection.HashableString;
import se.penselnsvag.bookdb.tech.log.imp.Log4jLoggerImp;

/**
* LogManager, responsible for managing Logger objects.
*
* Author:christian.vejrich@gimlet.se
* Date: 2005-07-07
* Version: 1.0
* History: -
*/
public class LogManager  
{
	private static var loggerMap:HashMap = new HashMap();
	public static const DEBUG_LOG_LEVEL:Number = 5;
	public static const INFO_LOG_LEVEL:Number = 4;
	public static const WARNING_LOG_LEVEL:Number = 3;
	public static const ERROR_LOG_LEVEL:Number = 2;
	public static const FATAL_LOG_LEVEL:Number = 1; 
	
	public static const INITIALIZED_MESSAGE:String = "Initialized";
	
	private static const STR_DEBUG_LOG_LEVEL:String = "DEBUG";
	private static const STR_INFO_LOG_LEVEL:String = "INFO";
	private static const STR_WARNING_LOG_LEVEL:String = "WARNING";
	private static const STR_ERROR_LOG_LEVEL:String = "ERROR";
	private static const STR_FATAL_LOG_LEVEL:String = "FATAL"; 
	
	private var isInitialized:Boolean = false;
	private var logger:LoggerInterface; 
	
	
	/**
	* Singelton
	*/
	public function LogManager(){
		init();
	}
	private static var instance:LogManager = null;
	public static function getInstance():LogManager
	{
		if (instance == null) {
			instance= new LogManager();
		}
		return instance;		
	}
	
	/**
	* getLogLevel
	*/
	public static function getLogLevelName(logLevel:Number) : String
	{
		switch(logLevel)
		{
			case LogManager.DEBUG_LOG_LEVEL : return LogManager.STR_DEBUG_LOG_LEVEL; break; 
			case LogManager.INFO_LOG_LEVEL : return LogManager.STR_INFO_LOG_LEVEL; break;
			case LogManager.WARNING_LOG_LEVEL : return LogManager.STR_WARNING_LOG_LEVEL; break;
			case LogManager.ERROR_LOG_LEVEL : return LogManager.STR_ERROR_LOG_LEVEL; break;
			case LogManager.FATAL_LOG_LEVEL : return LogManager.STR_FATAL_LOG_LEVEL; break;
			default: break;
		}
		return "";
	}
	
	public static function getLogLevel(logLevelName:String) : Number
	{
		switch(logLevelName)
		{
			case LogManager.STR_DEBUG_LOG_LEVEL : return LogManager.DEBUG_LOG_LEVEL; break; 
			case LogManager.STR_INFO_LOG_LEVEL : return LogManager.INFO_LOG_LEVEL; break; 
			case LogManager.STR_WARNING_LOG_LEVEL : return LogManager.WARNING_LOG_LEVEL; break;
			case LogManager.STR_ERROR_LOG_LEVEL : return LogManager.ERROR_LOG_LEVEL; break;
			case LogManager.STR_FATAL_LOG_LEVEL : return LogManager.FATAL_LOG_LEVEL; break;
			default: break;
		}
		return -1;
	}
	
	
	public function getLogger(o:Object):LoggerInterface {
		var name:String = getQualifiedClassName(o);
		var javaStyleeName:String = name.replace("::", ".");
		return getLog(javaStyleeName);
	}
	
	/**
	* getLog();
	*
	* Returns Logger associated with public class.   
	*
	* @param objcet
	* @return LoggerInterface
	*/
	public function getLog(classNameP:String) : LoggerInterface
	{
		var methodName:String = "getLog";
		
		//logger.debug(new LogMessage(Constants.LOG_ENTERING_MESSAGE,LogManager.className,methodName,null));
		
		if(!isInitialized)
		{
			init();
		}
		
		var searchArray:Array = toSearchArray(classNameP); 
		var log:LoggerInterface;

		for(var i:Number = 0 ; (searchArray!=null) && i != searchArray.length ; i++)
		{
			log = LoggerInterface(loggerMap.get(new HashableString(String(searchArray[i]))));
			if( log != null)
			{
				break;
			}
		}	
//		logger.debug(new LogMessage(Constants.LOG_LEAVING_MESSAGE,LogManager.className,methodName,null));
		if(log is Log4jLoggerImp){
			var log4j:Log4jLoggerImp = Log4jLoggerImp(log);
			log4j = log4j.clone();
			log4j.setClassName(classNameP);
			
			return log4j;
		}
			
		return log;
	}
	
	/**
	* toSearchArray,
	*
	* @param Class name - to build search array from.
	* @return Array - with search keys.
	*/
	private function toSearchArray(className:String) : Array
	{
		var methodName:String = "toSearchArray";		
		var stringKey:String = "";
		var stringKeyArray:Array;
		stringKeyArray = className.split(".");
			
		var keyArray:Array = new Array();	
			
		for(var i:int = 0 ; (stringKeyArray!=null) && i != stringKeyArray.length ; i++)
		{
			stringKey += String(stringKeyArray[i]) + ".";
			keyArray.push(stringKey);
		}
		keyArray.reverse();

		return keyArray;
	}
	
	/**
	* init(),
	*
	* Write config code here.
	*/
	private function init() : void
	{
		isInitialized = true;
		//Initilize with root logger.
		var methodName : String = "init";		
		loggerMap.put(new HashableString("se."),new Log4jLoggerImp(LogManager.DEBUG_LOG_LEVEL));
		loggerMap.put(new HashableString("mxml."),new Log4jLoggerImp(LogManager.DEBUG_LOG_LEVEL));
		
		this.logger = this.getLogger(this);
		if (this.logger == null)
			trace("LogManager :: NOT Initialized.");
		
	}
	
	public function getGrid():Array {
		var grid:Array = new Array();
		var keys:Array = loggerMap.getKeys();
		for(var i:int = 0 ; i<keys.length ; i++) {
			var pkg:HashableString = HashableString(keys[i]);
			var loggerType:LoggerInterface = LoggerInterface(loggerMap.get(pkg));
			var loggerTypeStr : String = findType(loggerType);
			var level:Object = new Object(); 
			level.value = loggerType.getLogLevel();
			level.label = LogManager.getLogLevelName(loggerType.getLogLevel());
			grid.push({ pkg:pkg, type:loggerTypeStr, level:level});
		}
		
		return(grid);
	}
	
	public function putLogger(pkg:String, l:LoggerInterface):void {
		loggerMap.put(new HashableString(pkg), Object(l));
	}
	
	public function removeLogger(pkg:String):void {
		loggerMap.remove(new HashableString(pkg));
	}
	
	private function findType(l:LoggerInterface):String {
		if(l is Log4jLoggerImp)
			return "Log4j";
		return "";		
	}
}
}